###############################################################################
# SuperLinks                                                                  #
# Copyright (c) 2000-2007 Greg Nolle (http://greg.nolle.co.uk)                #
###############################################################################
# This program is free software; you can redistribute it and/or modify it     #
# under the terms of the GNU General Public License as published by the Free  #
# Software Foundation; either version 2 of the License, or (at your option)   #
# any later version.                                                          #
#                                                                             #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   #
# more details.                                                               ##                                                                             #
# You should have received a copy of the GNU General Public License along     #
# with this program; if not, write to the Free Software Foundation, Inc.,     #
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.                 #
###############################################################################
# Libraries/Standard.pm.pl -> Standard library                                #
###############################################################################
# DON'T EDIT BELOW UNLESS YOU KNOW WHAT YOU'RE DOING!                         #
###############################################################################
package Standard;

BEGIN { require "System.pm.pl"; import System qw($SYSTEM); }
BEGIN { require "General.pm.pl"; import General qw($GENERAL); }
require "Error.pm.pl";

use Template;
use POSIX;
use strict;

###############################################################################
# Substitute subroutine
sub Substitute {
  my %in = (
    "STANDARD"	  => 0,
    "INPUT"       => "",
    "FIELDS"      => {},
    @_
  );

  my %Options;
  
  $Options{'INCLUDE_PATH'} = "$SL::PATH/Private/Skins/Templates/$SL::SKIN{'TEMPLATESET'}";
  $Options{'ABSOLUTE'}     = 1;
  $Options{'RELATIVE'}     = 1;
  $Options{'START_TAG'}    = quotemeta($SYSTEM->{'START_TAG'});
  $Options{'END_TAG'}      = quotemeta($SYSTEM->{'END_TAG'});
  
  if ($SYSTEM->{'CACHING'} eq "template") {
    $Options{'COMPILE_DIR'} = $SYSTEM->{'CACHE_PATH'};
    $Options{'COMPILE_EXT'} = ".ttc";
  }

  my $Template = Template->new(%Options);
  
  if ($in{'STANDARD'}) {
    $in{'FIELDS'}->{'style'} ||= eval($SL::SKIN{'stylesheet'}->{'STYLESHEET'});

    $in{'FIELDS'}->{'system'}  = $SYSTEM;
    $in{'FIELDS'}->{'general'} = $GENERAL;
    $in{'FIELDS'}->{'query'}   = \%SL::QUERY;
    $in{'FIELDS'}->{'global'}  = \%SL::GLOBAL;
    $in{'FIELDS'}->{'skin'}    = \%SL::SKIN;

    $Template->context->define_filter("round", \&Round);

    require "Templates/Form.pm.pl";
    $in{'FIELDS'}->{'form'}    = Form->new();
    
    require "Templates/Tools.pm.pl";
    $in{'FIELDS'}->{'tools'}   = Tools->new();
    
    foreach my $key (keys %SL::TAGS) {
      $in{'FIELDS'}->{$key} = $SL::TAGS{$key};
    }
  }

  my $Return;
  unless ($Template->process($in{'INPUT'}, $in{'FIELDS'}, \$Return)) {
    &Error::CGIError("Error processing template. ".&HTMLize($Template->error()), "");
  }
  
  return $Return;
}

###############################################################################
# ShowStatic subroutine
sub ShowStatic {
  my %in = ("DB" => undef, "TYPE" => "", "ID" => "", "PAGE" => "", @_);

  return 1 unless ($SYSTEM->{'CACHING'} eq "static");
  return 1 if ($SL::QUERY{'NoStatic'});

  $in{'PAGE'} ||= 1;

  if ($in{'TYPE'} eq "Detail") {
    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Detail/$in{'ID'}.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Detail/$in{'ID'}.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Detail/$in{'ID'}.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Detail/$in{'ID'}.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Detail/$in{'ID'}.html\n\n";
        exit;
      }
    }

    require "StaticPages.pm.pl";
    my $StaticPages = StaticPages->new(DB => $in{'DB'});
       $StaticPages->Build(TYPE => "Detail", ID => $in{'ID'}) || return;

    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Detail/$in{'ID'}.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Detail/$in{'ID'}.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Detail/$in{'ID'}.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Detail/$in{'ID'}.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Detail/$in{'ID'}.html\n\n";
        exit;
      }
    }
  } elsif ($in{'TYPE'} eq "Category") {
    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Category/$in{'ID'}-$in{'PAGE'}.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Category/$in{'ID'}-$in{'PAGE'}.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Category/$in{'ID'}-$in{'PAGE'}.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Category/$in{'ID'}-$in{'PAGE'}.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Category/$in{'ID'}-$in{'PAGE'}.html\n\n";
        exit;
      }
    }

    require "StaticPages.pm.pl";
    my $StaticPages = StaticPages->new(DB => $in{'DB'});
       $StaticPages->Build(TYPE => "Category", ID => $in{'ID'}, PAGE => $in{'PAGE'}) || return;

    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Category/$in{'ID'}-$in{'PAGE'}.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Category/$in{'ID'}-$in{'PAGE'}.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Category/$in{'ID'}-$in{'PAGE'}.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Category/$in{'ID'}-$in{'PAGE'}.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Category/$in{'ID'}-$in{'PAGE'}.html\n\n";
        exit;
      }
    }
  } elsif ($in{'TYPE'} eq "Index") {
    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Index.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Index.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Index.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Index.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Index.html\n\n";
        exit;
      }
    }

    require "StaticPages.pm.pl";
    my $StaticPages = StaticPages->new(DB => $in{'DB'});
       $StaticPages->Build(TYPE => "Index") || return;

    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Index.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Index.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Index.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Index.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Index.html\n\n";
        exit;
      }
    }
  } elsif ($in{'TYPE'} eq "Cool") {
    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Cool.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Cool.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Cool.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Cool.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Cool.html\n\n";
        exit;
      }
    }

    require "StaticPages.pm.pl";
    my $StaticPages = StaticPages->new(DB => $in{'DB'});
       $StaticPages->Build(TYPE => "Cool") || return;

    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Cool.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Cool.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Cool.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Cool.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Cool.html\n\n";
        exit;
      }
    }
  } elsif ($in{'TYPE'} eq "Hot") {
    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Hot.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Hot.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Hot.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Hot.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Hot.html\n\n";
        exit;
      }
    }

    require "StaticPages.pm.pl";
    my $StaticPages = StaticPages->new(DB => $in{'DB'});
       $StaticPages->Build(TYPE => "Hot") || return;

    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Hot.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Hot.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Hot.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/Hot.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/Hot.html\n\n";
        exit;
      }
    }
  } elsif ($in{'TYPE'} eq "New") {  
    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/New.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/New.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/New.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/New.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/New.html\n\n";
        exit;
      }
    }

    require "StaticPages.pm.pl";
    my $StaticPages = StaticPages->new(DB => $in{'DB'});
       $StaticPages->Build(TYPE => "New") || return;

    unless (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/New.del") {
      if (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/New.shtml") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/New.shtml\n\n";
        exit;
      } elsif (-e "$SYSTEM->{'PUBLIC_PATH'}/Static/New.html") {
        print "Location: $SYSTEM->{'PUBLIC_URL'}/Static/New.html\n\n";
        exit;
      }
    }
  }
    
  return;  
}

###############################################################################
# ProcessPlugins subroutine
sub ProcessPlugins {
  
  opendir(PLUGINS, "$SL::PATH/Private/Plugins");
  foreach my $file (grep(/\.pm\.pl$/i, readdir(PLUGINS))) {
    eval {
      require "$SL::PATH/Private/Plugins/$file";
      my $Plugin = Plugin->new();
      return unless ($Plugin);
    
      foreach my $key (keys %{ $Plugin->{'TAGS'} }) {
        $SL::TAGS{$key} = $Plugin->{'TAGS'}->{$key};
      }
      foreach my $key (keys %{ $Plugin->{'ACTIONS'}->{'SL'} }) {
        $SL::ACTIONS{'SL'}->{$key} = $Plugin->{'ACTIONS'}->{'SL'}->{$key};
      }
      foreach my $key (keys %{ $Plugin->{'ACTIONS'}->{'CP'} }) {
        $SL::ACTIONS{'CP'}->{$key} = $Plugin->{'ACTIONS'}->{'CP'}->{$key};
      }
      push(@SL::CPMENU, @{ $Plugin->{'CPMENU'} });
    };
  }
  closedir(DIR);
  
  return 1;
}

###############################################################################
# FilterWords subroutine
sub FilterWords {
  my ($String) = @_;
  
  foreach my $word (@{ $GENERAL->{'BAN_WORDS'} }) {
    my $sub = $word;
       $sub =~ s//\*/g;
    $String =~ s/$word/$sub/g;
  }
  
  return $String;
}

###############################################################################
# FileOpen function
sub FileOpen {
  my ($FileHandle, $AccessMode, $FileName, $skip) = @_;
  $FileName   =~ s/\|//g;
  $FileName   =~ s/\>//g;
  $FileName   =~ s/\<//g;

  $FileName =~ /^(.+)\/[^\/]+$/;
  my $Path = $1;

  my $Mode;
  if ($AccessMode eq "a") {
    if (-e $FileName) {
      $Mode = ">>";
    } else {
      $Mode = ">";
    }
  } elsif ($AccessMode eq "w") {
    $Mode = ">";
  } elsif ($AccessMode eq "r") {
    $Mode = "";
  } elsif ($AccessMode eq "rw") {
    unless (-e $FileName) {
      open ($FileHandle, ">".$FileName);
      close ($FileHandle);
    }
    $Mode = "";
  }

  chmod (0777, $FileName);

  unless (open ($FileHandle, $Mode.$FileName)) {
    if ($AccessMode eq "a") {
      &Error::CGIError("Can't open file for appending. $!", $FileName) unless $skip;
      return;
    } elsif ($AccessMode eq "w") {
      &Error::CGIError("Can't open file for writing. $!"  , $FileName) unless $skip;
      return;
    } elsif ($AccessMode eq "r") {
      &Error::CGIError("Can't open file for reading. $!"  , $FileName) unless $skip;
      return;
    }
  }

  chmod (0766, $FileName);

  if ($SYSTEM->{'FLOCK'} == 1) {
    if ($AccessMode ne "r") {
      flock ($FileHandle, 2);
    } else {
      flock ($FileHandle, 1);
    }
  }

  return 1;
}

###############################################################################
# lock function
sub lock {
  my ($file)  = @_;
  my $EndTime = 30 + time;

  while ((-e $file) && (time < $EndTime)) {
    sleep(1);
  }

  chmod (0777, $SYSTEM->{'TEMP_PATH'});

  open(LOCK, ">$SYSTEM->{'TEMP_PATH'}/$file") || &Error::CGIError("Can't open a file for locking. $!", "$SYSTEM->{'TEMP_PATH'}/$file");
  chmod (0777, "$SYSTEM->{'TEMP_PATH'}/$file");
}

###############################################################################
# unLock function
sub unLock {
  my ($file) = @_;

  close(LOCK);

  unlink("$SYSTEM->{'TEMP_PATH'}/$file");
}

###############################################################################
# PrintHTMLHeader function
sub PrintHTMLHeader {
  return if ($SL::HTML_HEADER);
  
  my $Path = $SYSTEM->{'SCRIPT_URL'};
     $Path =~ s/^http(s)?\:\/\/(.*?)\//\//;
  my $Cookie = $SL::CGI->cookie(
    -name     => "SuperLinks",
    -value    => \%SL::COOKIES,
    -expires  => "+30d",
    -path     => $Path
  );

  print $SL::CGI->header(-cookie => $Cookie, -charset => $SYSTEM->{'CHARSET'});
  $SL::HTML_HEADER = 1;
}

###############################################################################
# ParseForm function
sub ParseForm {
  foreach my $keyword ($SL::CGI->param()) {
    $SL::QUERY{ $keyword } = $SL::CGI->param( $keyword );
  }
}

###############################################################################
# ParseCookies function
sub ParseCookies {
  %SL::COOKIES = $SL::CGI->cookie("SuperLinks");
}

###############################################################################
# SetSkin function
sub SetSkin {
  my %in = ("DB" => undef, "SKIN" => "", @_);
  
  my $Skin;

  {
    if ($in{'SKIN'}) {
      my $skin = eval($in{'SKIN'});
    
      if ($skin->{'CUSTOM'}) {
        $Skin->{'TEMPLATESET'} = $skin->{'TEMPLATESET'};
        $Skin->{'LANGUAGESET'} = $skin->{'LANGUAGESET'};
        $Skin->{'STYLESHEET'}  = $skin->{'STYLESHEET'};
        last;
      } else {
        $Skin = $in{'DB'}->BinarySelect(
          TABLE   => "Skins",
          KEY     => $skin->{'ID'}
        );
        last if ($Skin);
      }
    }  

    if ($SL::QUERY{'ForceSkin'}) {
      $Skin = $in{'DB'}->BinarySelect(
        TABLE   => "Skins",
        KEY     => $SL::QUERY{'ForceSkin'}
      );
      if ($Skin) {
        $SL::COOKIES{'SKIN'} = $SL::QUERY{'ForceSkin'};
        last;
      }
    }
  
    $SL::COOKIES{'SKIN'} = "" if ($SL::QUERY{'NoForceSkin'});
  
    if ($SL::QUERY{'Skin'}) {
      $Skin = $in{'DB'}->BinarySelect(
        TABLE   => "Skins",
        KEY     => $SL::QUERY{'Skin'}
      );
      last if ($Skin);
    }
  
    if ($SL::COOKIES{'SKIN'}) {
      $Skin = $in{'DB'}->BinarySelect(
        TABLE   => "Skins",
        KEY     => $SL::COOKIES{'SKIN'}
      );
      if ($Skin) {
        last;
      } else {
        $SL::COOKIES{'SKIN'} = "";
      }
    }

    $Skin = $in{'DB'}->BinarySelect(
      TABLE   => "Skins",
      KEY     => $GENERAL->{'SKIN'}
    );
  }

  $Skin->{'templateset'} = $in{'DB'}->BinarySelect(
    TABLE   => "TemplateSets",
    KEY     => $Skin->{'TEMPLATESET'}
  );

  $Skin->{'languageset'} = $in{'DB'}->BinarySelect(
    TABLE   => "LanguageSets",
    KEY     => $Skin->{'LANGUAGESET'}
  );

  $Skin->{'stylesheet'} = $in{'DB'}->BinarySelect(
    TABLE   => "StyleSheets",
    KEY     => $Skin->{'STYLESHEET'}
  );

  %SL::SKIN = %{ $Skin };

  return 1;
}

###############################################################################
# ProcessError function
sub ProcessError {
  my %in = ("LANGUAGE" => undef, "ERROR" => undef, @_);

  return unless ($in{'ERROR'});

  my $LANGUAGE;
  
  if (ref($in{'LANGUAGE'}) eq "HASH") {
    $LANGUAGE = $in{'LANGUAGE'};
  } else {
    $LANGUAGE = &GetLanguage($in{'LANGUAGE'});
  }

  $in{'ERROR'} = [$in{'ERROR'}] unless (ref($in{'ERROR'}) eq "ARRAY");

  my $Return;
  foreach my $error (@{ $in{'ERROR'} }) {
    if ($error =~ /^MISSING-(.*)$/ && $LANGUAGE->{'MISSING'}->{ $1 }) {
      $Return .= $LANGUAGE->{'MISSING'}->{ $1 };
    } elsif ($error =~ /^INVALID-(.*)$/ && $LANGUAGE->{'INVALID'}->{ $1 }) {
      $Return .= $LANGUAGE->{'INVALID'}->{ $1 };
    } elsif ($error =~ /^TOOLONG-(.*)$/ && $LANGUAGE->{'TOOLONG'}->{ $1 }) {
      $Return .= $LANGUAGE->{'TOOLONG'}->{ $1 };
    } elsif ($error =~ /^ALREADYEXISTS-(.*)$/ && $LANGUAGE->{'ALREADYEXISTS'}->{ $1 }) {
      $Return .= $LANGUAGE->{'ALREADYEXISTS'}->{ $1 };
    } elsif ($LANGUAGE->{ $error }) {
      $Return .= $LANGUAGE->{ $error };
    } else {
      $Return .= $error;
    }
  }

  return unless ($Return);

  my $StartTag = quotemeta($SYSTEM->{'START_TAG'});
  if ($Return =~ /$StartTag/) {
    $Return = &Substitute(
      INPUT     => \$Return,
      STANDARD  => 1
    );
  }

  return &Substitute(
    INPUT     => \$LANGUAGE->{'ERROR'},
    STANDARD  => 1,
    FIELDS    => { error => $Return }
  );
}

###############################################################################
# GetLanguage function
sub GetLanguage {
  my ($Language) = @_;

  require "Skins/Language/$SL::SKIN{'LANGUAGESET'}/$Language.pm.pl";
  
  return eval("return \$Language::".$Language."::LANGUAGE;");
}

###############################################################################
# ConvertEpochToDate function
sub ConvertEpochToDate {
  my ($Epoch) = @_;

  $Epoch = time unless ($Epoch);

  my @Months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");

  my (undef, $min, $hour, $mDay, $mon, $year, $wDay, undef) = gmtime($Epoch + ($SYSTEM->{'LOCALTIME_OFFSET'} * 60 * 60));

  if ($SYSTEM->{'LOCALTIME_DST'} && (
    ($mon > 3 && $mon < 9)                                                ||
    ($mon == 3 && $mDay > 7)                                              ||
    ($mon == 3 && $mDay <= 7 && $wDay == 0 && $hour >= 2)                 ||
    ($mon == 3 && $mDay <= 7 && $wDay != 0 && ($mDay - $wDay) > 0)        ||
    ($mon == 10 && $mDay < 25)                                            ||
    ($mon == 10 && $mDay >= 25 && $wDay == 0 && $hour < 2)                ||
    ($mon == 10 && $mDay >= 25 && $wDay != 0 && ($mDay - 24 - $wDay) < 1)
  )) {
    (undef, undef, undef, $mDay, $mon, $year, undef, undef) = gmtime($Epoch + ($SYSTEM->{'LOCALTIME_OFFSET'} * 60 * 60) + (60 * 60));
  }

  my $Date;

  $year += 1900;

  if ($GENERAL->{'DATE_FORMAT'} eq "US") {
    $Date = sprintf ("%02d-%02d-%04d", $mon + 1, $mDay, $year);
  } elsif ($GENERAL->{'DATE_FORMAT'} eq "USE") {
    $Date = sprintf ("%s %02d, %04d", $Months[$mon], $mDay, $year);
  } elsif ($GENERAL->{'DATE_FORMAT'} eq "EU") {
    $Date = sprintf ("%02d-%02d-%04d", $mDay, $mon + 1, $year);
  } elsif ($GENERAL->{'DATE_FORMAT'} eq "EUE") {
    $Date = sprintf ("%02d %s, %04d", $mDay, $Months[$mon], $year);
  } else {
    $Date = sprintf ("%02d-%02d-%04d", $mon + 1, $mDay, $year);
  }

  return $Date;
}

###############################################################################
# ConvertEpochToTime function
sub ConvertEpochToTime {
  my ($Epoch) = @_;

  $Epoch = time unless ($Epoch);

  my (undef, $min, $hour, $mDay, $mon, $year, $wDay, undef) = gmtime($Epoch + ($SYSTEM->{'LOCALTIME_OFFSET'} * 60 * 60));

  if ($SYSTEM->{'LOCALTIME_DST'} && (
    ($mon > 3 && $mon < 9)                                                ||
    ($mon == 3 && $mDay > 7)                                              ||
    ($mon == 3 && $mDay <= 7 && $wDay == 0 && $hour >= 2)                 ||
    ($mon == 3 && $mDay <= 7 && $wDay != 0 && ($mDay - $wDay) > 0)        ||
    ($mon == 10 && $mDay < 25)                                            ||
    ($mon == 10 && $mDay >= 25 && $wDay == 0 && $hour < 2)                ||
    ($mon == 10 && $mDay >= 25 && $wDay != 0 && ($mDay - 24 - $wDay) < 1)
  )) {
    (undef, $min, $hour, undef, undef, undef, undef, undef) = gmtime($Epoch + ($SYSTEM->{'LOCALTIME_OFFSET'} * 60 * 60) + (60 * 60));
  }

  my $Time;
	
  if ($GENERAL->{'TIME_FORMAT'} eq "12") {
    if ($hour >= 12) {
      $hour -= 12 if ($hour > 12);
      $Time = sprintf ("%02d:%02d p.m.", $hour, $min);
    } else {
      $hour = 12 if ($hour == 0);
      $Time = sprintf ("%02d:%02d a.m.", $hour, $min);
    }
  } else {
    $Time = sprintf ("%02d:%02d", $hour, $min);
  }

  return $Time;
}

###############################################################################
# HTMLize function
sub HTMLize {
  my ($Data) = @_;

  $Data =~ s/\&/\&amp\;/g;
  $Data =~ s/\</\&lt\;/g;
  $Data =~ s/\>/\&gt\;/g;
  $Data =~ s/\"/\&quot\;/g;
  $Data =~ s/\'/\&#39\;/g;
  #$Data =~ s/\|/\&\#124\;/g;
  $Data =~ s/\r//g;

  return $Data;
}

###############################################################################
# Textize function
sub Textize {
  my ($Data) = @_;

  $Data =~ s/\&amp\;/\&/g;
  $Data =~ s/\&lt\;/\</g;
  $Data =~ s/\&gt\;/\>/g;
  $Data =~ s/\&quot\;/\"/g;
  $Data =~ s/\&#39\;/\'/g;
  #$Data =~ s/\&\#124\;/\|/g;

  return $Data;
}

###############################################################################
# MapArray function
sub MapArray {
  my ($Template, $Data, $Join) = @_;

  if (ref($Template) eq "HASH") {
    my %template;
    foreach my $key (keys %{ $Template }) {
      my $value = $Template->{$key};
      
      $key =~ s/\$\{\}/\$record/ig;
      $key =~ s/\$\{([\.\w]+)\}/\$record->{\'$1\'}/ig;
      $value =~ s/\$\{\}/\$record/ig;
      $value =~ s/\$\{([\.\w]+)\}/\$record->{\'$1\'}/ig;
      
      $template{ $key } = $value;
    }
    $Template = \%template;
  } elsif (ref($Template) eq "ARRAY") {
    foreach my $value (@{ $Template }) {
      $value =~ s/\$\{\}/\$record/ig;
      $value =~ s/\$\{([\.\w]+)\}/\$record->{\'$1\'}/ig;
    }
  } else {
    $Template =~ s/\$\{\}/\$record/ig;
    $Template =~ s/\$\{([\.\w]+)\}/\$record->{\'$1\'}/ig;
  }

  my @Return;
  
  foreach my $record (@{ $Data }) {
    if (ref($Template) eq "HASH") {
      my %return;
      foreach my $key (keys %{ $Template }) {
        $return{ eval("return \"$key\"") } = eval("return \"$Template->{$key}\"");
      }
      push(@Return, \%return);
    } elsif (ref($Template) eq "ARRAY") {
      my @return;
      foreach my $value (@{ $Template }) {
        push(@return, eval("return \"$value\""));
      }
      push(@Return, \@return);
    } else {
      push(@Return, eval("return \"$Template\""));
    }
  }
  
  if ($Join) {
    return join($Join, @Return);
  } else {
    return @Return;
  }
}

###############################################################################
# GetPages subroutine
sub GetPages {
  my ($Page, $Items, $PerPage) = @_;

  my %Return;
  
  $Return{'page'}     = $Page || 1;
  $Return{'start'}    = ($Return{'page'} - 1) * $PerPage;
  $Return{'finish'}   = $Return{'start'} + $PerPage - 1;
  $Return{'finish'}   = ($Items - 1) if ($Return{'finish'} >= $Items);
  $Return{'count'}    = ceil($Items / $PerPage);
  $Return{'count'}    = 1 if ($Return{'count'} < 1);
  $Return{'items'}    = $Items;
  
  $Return{'previous'} = $Return{'page'} - 1 unless ($Return{'page'} == 1);
  $Return{'next'}     = $Return{'page'} + 1 unless ($Return{'page'} == $Return{'count'});
  
  for (my $h = 1; $h <= $Return{'count'}; $h++) {
    push(@{ $Return{'pages'} }, $h);
  }

  return \%Return;
}

###############################################################################
# ArrayToHash subroutine
sub ArrayToHash {
  my ($Array, $Value) = @_;
  
  $Value ||= 1;
  
  my %Return;
  foreach my $value (@{ $Array }) {
    $Return{ $value } = $Value;
  }
  
  return \%Return;
}

###############################################################################
# Round subroutine
sub Round {
  my ($Input) = @_;

  my ($Whole, $Fraction) = split(/\./, $Input);
  $Fraction = "0.".$Fraction;
  
  if ($Fraction >= 0.5) {
    return ($Whole + 1);
  } else {
    return $Whole;
  }
}

1;